#ifndef _XBENCH_TIMER_H
#define _XBENCH_TIMER_H

#include <chrono>
#include <optional>
#include <cstdint>

namespace xbench{
    class Timer {
    private:
        enum class TimerCurrentState {
            Stop,
            Run,
            End
        };

        TimerCurrentState _state;
        std::chrono::steady_clock::time_point _start;
        std::chrono::steady_clock::time_point _end;

        template<class _time>
        [[nodiscard]] int64_t duration() const noexcept{
            if (this->_state != TimerCurrentState::End)
                // 只有处在End状态才能有效调用duration方法
                return -1;
            auto t = std::chrono::duration_cast<_time>(this->_end - this->_start);
            return t.count();
        };

    public:
        Timer() : _state(TimerCurrentState::Stop){};
        Timer(const std::chrono::steady_clock::time_point& start, const std::chrono::steady_clock::time_point& end):
            _start(start), _end(end), _state(TimerCurrentState::End){};

        bool start();
        bool cancel();
        void reset();
        void restart();

        [[nodiscard]] const std::chrono::steady_clock::time_point& start_time() const;
        [[nodiscard]] const std::chrono::steady_clock::time_point& end_time() const;

        [[nodiscard]] inline int64_t duration_ms() const noexcept {
            return this->duration<std::chrono::milliseconds>();
        };

        [[nodiscard]] inline int64_t duration_ns() const noexcept {
            return this->duration<std::chrono::nanoseconds>();
        };
    };

    class TimerRecord{
    private:
        int64_t _start_ns;
        int64_t _duration_ns;
    public:
        TimerRecord() = default;
        explicit TimerRecord(const xbench::Timer& timer);

        [[nodiscard]] constexpr int64_t start_ns() const noexcept { return this->_start_ns; };
        [[nodiscard]] constexpr int64_t duration_ns() const noexcept { return this->_duration_ns; };
    };
}

#endif //_XBENCH_TIMER_H
